package com.tm.aop;


import com.tm.annotation.WmLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class OperationLogAspect {


    /**
     * 切点
     */
    @Bean
    @Pointcut("@annotation(com.tm.annotation.WmLog)")
    public void cut(){}


    @Before("cut()")
    public void before(JoinPoint joinPoint){
        log.info("前置通知");
    }

    /**
     * 环绕通知
     */
    @Around("cut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //TODO 前置通知之后 执行业务逻辑之前
        log.info("环绕通知1");
        long startTime = System.currentTimeMillis();
        //执行业务
        Object result = proceedingJoinPoint.proceed();
        log.info("环绕通知2");
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        WmLog annotation = method.getAnnotation(WmLog.class);
        String operationModule = annotation.operationModule();
        String operationTypeEnum = annotation.operationType().getOperationType();
        String description = annotation.description();
        log.info("操作模块：[{}],操作类型：[{}],描述：[{}]",operationModule,operationTypeEnum,description);
        log.info("接口执行耗时：[{}]毫秒",System.currentTimeMillis()-startTime);
        return result;
    }

    /**
     * 后置通知
     */
    @After("cut()")
    public void after(JoinPoint joinPoint){
        joinPoint.getClass();
        log.info("后置通知");
    }

    /**
     * 返回通知
     */
    @AfterReturning(pointcut = "cut()",returning = "joinResult" )
    public void afterReturning(JoinPoint joinPoint ,Object joinResult){
        log.info("返回通知");
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private WmLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(WmLog.class);
        }
        return null;
    }

    /**
     * 获取参数Map集合
     *
     * @param joinPoint
     * @return
     */
    Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
        Map<String, Object> param = new HashMap<>();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < paramNames.length; i++) {
            param.put(paramNames[i], paramValues[i]);
        }
        return param;
    }

    /**
     * 异常通知
     */
    @AfterThrowing(value = "cut()" ,throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Exception e){
        log.info("异常通知");
    }
}
